package com.kunzisoft.switchdatetime;

import com.kunzisoft.switchdatetime.date.OnYearSelectedListener;
import com.kunzisoft.switchdatetime.date.widget.ListPickerYearView;
import com.kunzisoft.switchdatetime.event.MessageEvent;
import com.kunzisoft.switchdatetime.provider.PageProvider;
import com.kunzisoft.switchdatetime.time.RadialPickerLayout;
import com.kunzisoft.switchdatetime.time.SwitchTimePicker;
import ohos.aafwk.ability.Ability;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.TextTool;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.data.DatabaseHelper;
import ohos.data.preferences.Preferences;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SwitchDateTimeDialogFragment extends CommonDialog {
    private static final String TAG = "SwitchDateTimeDialogFrg";

    private static final String STATE_DATETIME = "STATE_DATETIME";
    private static final String STATE_CURRENT_POSITION = "STATE_CURRENT_POSITION";

    private static final int UNDEFINED_POSITION = -1;
    private static boolean isOrientation;
    private final Preferences mTimeDataSave;
    private Calendar dateTimeCalendar = Calendar.getInstance();
    private Calendar minimumDateTime = new GregorianCalendar(1970, 1, 1);
    private Calendar maximumDateTime = new GregorianCalendar(2200, 1, 1);
    private TimeZone timeZone = TimeZone.getDefault();

    private static final String TAG_LABEL = "LABEL";
    private static final String TAG_POSITIVE_BUTTON = "POSITIVE_BUTTON";
    private static final String TAG_NEGATIVE_BUTTON = "NEGATIVE_BUTTON";
    private static final String TAG_NEUTRAL_BUTTON = "NEUTRAL_BUTTON";

    private String mLabel;
    private String mPositiveButton;
    private String mNegativeButton;
    private String mNeutralButton;
    private OnButtonClickListener mListener;

    private boolean is24HoursMode = false;
    private boolean highlightAMPMSelection = false;
    private int startAtPosition = 1;
    private int currentPosition = 0;
    private int alertStyleId;

    private SimpleDateFormat dayAndMonthSimpleDate;
    private SimpleDateFormat yearSimpleDate;

    private PageFlipper viewSwitcher;
    private SwitchTimePicker timePicker;
    //    private MaterialCalendarView materialCalendarView;
    private ListPickerYearView listPickerYearView;

    private Text monthAndDayHeaderValues;
    private Text yearHeaderValues;

    private boolean blockAnimationIn;
    private boolean blockAnimationOut;

    private static Context mContext;
    private PageSlider pageSlider;
    private PageProvider pageProvider;
    private Image left_arrow;
    private Image right_arrow;
    private Text text_month;
    private Calendar calendar = Calendar.getInstance();
    private static final String[] MONTH_NAME = DateFormatSymbols.getInstance().getMonths();
    private int original_year = 2016;
    private int original_month = 2;
    private int original_day = 1;
    private Component dateTimeLayout;

    private String mouthArr[];
    /**
     * 当前系统语言是否是中文
     */
    private boolean isLaChina = true;
    private AnimatorGroup animatorGroup;

    private SwitchDateTimeDialogFragment(Context context) {
        super(context);

        // 获取保存的手机横竖屏情况（true - 竖屏；false - 横屏）
        DatabaseHelper databaseHelper = new DatabaseHelper(mContext);
        Preferences orientation = databaseHelper.getPreferences("ori_pref");
        mTimeDataSave = databaseHelper.getPreferences("time_pref");
        isOrientation = orientation.getBoolean("orientation", true);

        startAtPosition = mTimeDataSave.getInt("positionView", 1);
        System.out.println("-->>SwitchDateTimeDialogFragment = " + startAtPosition);
    }

    /**
     * Create a new instance of SwitchDateTimeDialogFragment
     *
     * @param label          Title of dialog
     * @param positiveButton Text for positive button
     * @param negativeButton Text for negative button
     * @param context        context
     * @return DialogFragment
     */
    public static SwitchDateTimeDialogFragment newInstance(Context context, String label, String positiveButton, String negativeButton) {
        return newInstance(context, label, positiveButton, negativeButton, null);
    }

    /**
     * SwitchDateTimeDialogFragment
     *
     * @param context        context
     * @param label          Title of dialog
     * @param positiveButton Text for positive button
     * @param negativeButton Text for negative button
     * @param neutralButton  Text for negative button
     * @return switchDateTimeDialogFragment
     */
    public static SwitchDateTimeDialogFragment newInstance(Context context, String label, String positiveButton,
                                                           String negativeButton, String neutralButton) {
        mContext = context;
        SwitchDateTimeDialogFragment switchDateTimeDialogFragment = new SwitchDateTimeDialogFragment(context);
        return switchDateTimeDialogFragment;
    }

    /**
     * Set listener for actions
     *
     * @param onButtonClickListener Listener for click
     */
    public void setOnButtonClickListener(OnButtonClickListener onButtonClickListener) {
        this.mListener = onButtonClickListener;
    }

    @Override
    protected void onCreate() {
        super.onCreate();
        EventBus.getDefault().register(this);
        dateTimeCalendar.setTimeZone(timeZone);

        if (Locale.getDefault().getLanguage().equals("zh")) {
            isLaChina = true;
            mouthArr = Utils.CH_MOUTH;
        } else {
            isLaChina = false;
            mouthArr = Utils.EN_MOUTH;
        }

        Display display = DisplayManager.getInstance().getDefaultDisplay(mContext).get();
        System.out.println("-->>onCreate.width:" + display.getAttributes().width + "--height:" + display.getAttributes().height);

        // Throw exception if default select date isn't between minimumDateTime and maximumDateTime
        if (dateTimeCalendar.before(minimumDateTime) || dateTimeCalendar.after(maximumDateTime))
            throw new RuntimeException("Default date " + dateTimeCalendar.getTime() + " must be between "
                    + minimumDateTime.getTime() + " and " + maximumDateTime.getTime());

        LayoutScatter inflater = LayoutScatter.getInstance(mContext);

        // 获取当前布局
        int xmlId;
        if (isOrientation) {
            xmlId = ResourceTable.Layout_dialog_switch_datetime_picker;
        } else {
            xmlId = ResourceTable.Layout_dialog_switch_datetime_picker_land;
        }
        dateTimeLayout = inflater.parse(xmlId,
                (ComponentContainer) ((Ability) mContext).findComponentById(ResourceTable.Id_datetime_picker),
                true);

        // Set label
        Text labelView = (Text) dateTimeLayout.findComponentById(ResourceTable.Id_label);
        if (mLabel != null)
            labelView.setText(mLabel);
        else
            labelView.setText(mContext.getString(ResourceTable.String_label_datetime_dialog));

        // Lock animation for fast clicks
        blockAnimationIn = false;
        blockAnimationOut = false;
        viewSwitcher = (PageFlipper) dateTimeLayout.findComponentById(ResourceTable.Id_dateSwitcher);

        AnimatorProperty inAnimation = new AnimatorProperty(viewSwitcher);
        inAnimation.moveFromX(840).moveToX(0).setDuration(500);
        viewSwitcher.setIncomingAnimation(inAnimation);
        viewSwitcher.getIncomingAnimation().setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
                blockAnimationIn = true;
            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {

            }

            @Override
            public void onEnd(Animator animator) {
                blockAnimationIn = false;
                currentPosition = viewSwitcher.getCurrentIndex();
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });
        AnimatorProperty outAnimation = new AnimatorProperty(viewSwitcher);
        outAnimation.moveByX(0).moveToX(-840).setDuration(500);
        viewSwitcher.setOutgoingAnimation(outAnimation);
        viewSwitcher.getOutgoingAnimation().setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {
                blockAnimationOut = true;
            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {

            }

            @Override
            public void onEnd(Animator animator) {
                blockAnimationOut = false;
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });

        // Defined the start position
        if (startAtPosition != UNDEFINED_POSITION) {
            currentPosition = startAtPosition;
        }
        viewSwitcher.setCurrentIndex(currentPosition);
        // viewSwitcher.setCurrentIndex(0);
        if (viewSwitcher.getCurrentIndex() == 0) {
            ((RadialPickerLayout) ((DirectionalLayout) viewSwitcher.getCurrentComponent()).getComponentAt(0)).refresh();
        }

        // Button for switch between Hours/Minutes, Calendar and YearList
        Image buttonSwitch = (Image) dateTimeLayout.findComponentById(ResourceTable.Id_button_switch);
        ShapeElement shapeElement = new ShapeElement();
        shapeElement.setRgbColor(RgbColor.fromArgbInt(Color.TRANSPARENT.getValue()));
        buttonSwitch.setBackground(shapeElement);
        buttonSwitch.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                Utils.animLabelElement(component);
                if (!(blockAnimationIn && blockAnimationOut)) {
                    viewSwitcher.showNext();
                    if (viewSwitcher.getCurrentIndex() == 0) {
                        ((RadialPickerLayout) ((DirectionalLayout) viewSwitcher.getCurrentComponent()).getComponentAt(0)).refresh();
                    }

                    if (mTimeDataSave != null) {
                        mTimeDataSave.putInt("positionView", viewSwitcher.getCurrentIndex());
                    }
                }
            }
        });

        // Values header hourOfDay minutes
        Component timeHeaderValues = dateTimeLayout.findComponentById(ResourceTable.Id_time_header_values);
        Component.ClickedListener onTimeClickListener =
                new OnClickHeaderElementListener(HeaderViewsPosition.VIEW_HOURS_AND_MINUTES.getPosition());
        timeHeaderValues.setClickedListener(onTimeClickListener);
        // Values header month day
        monthAndDayHeaderValues = (Text) dateTimeLayout.findComponentById(ResourceTable.Id_date_picker_month_and_day);
        Component.ClickedListener onMonthAndDayClickListener =
                new OnClickHeaderElementListener(HeaderViewsPosition.VIEW_MONTH_AND_DAY.getPosition());
        monthAndDayHeaderValues.setClickedListener(onMonthAndDayClickListener);
        // Values header year
        yearHeaderValues = (Text) dateTimeLayout.findComponentById(ResourceTable.Id_date_picker_year);
        Component.ClickedListener onYearClickListener =
                new OnClickHeaderElementListener(HeaderViewsPosition.VIEW_YEAR.getPosition());
        yearHeaderValues.setClickedListener(onYearClickListener);

        // Init simple date format if null
        if (dayAndMonthSimpleDate == null)
            dayAndMonthSimpleDate = new SimpleDateFormat("MMMM dd", Locale.getDefault());
        if (yearSimpleDate == null)
            yearSimpleDate = new SimpleDateFormat("yyyy", Locale.getDefault());

        dayAndMonthSimpleDate.setTimeZone(timeZone);
        yearSimpleDate.setTimeZone(timeZone);

        // Init headers
        yearHeaderValues.setText(yearSimpleDate.format(dateTimeCalendar.getTime()));
        if (isLaChina){
            monthAndDayHeaderValues.setText(dayAndMonthSimpleDate.format(dateTimeCalendar.getTime()));
        } else {
            String day;
            if (mTimeDataSave.getInt("day", 1) < 10) {
                day = " 0"+ mTimeDataSave.getInt("day", 1);
            } else {
                day = " " + mTimeDataSave.getInt("day", 1);
            }
            monthAndDayHeaderValues.setText(mTimeDataSave.getString("monthEn", "March") + day);
        }

        // Construct TimePicker
        SwitchTimePicker.OnTimeSelectedListener onTimeSelectedListener = new SwitchTimePicker.OnTimeSelectedListener() {
            @Override
            public void onTimeSelected(int hourOfDayTime, int minuteTime) {
                dateTimeCalendar.set(Calendar.HOUR_OF_DAY, hourOfDayTime);
                dateTimeCalendar.set(Calendar.MINUTE, minuteTime);
            }
        };
        // Init time with saved elements
        timePicker = new SwitchTimePicker(mContext, onTimeSelectedListener, null);
        timePicker.setIs24HourMode(is24HoursMode);
        timePicker.setHighlightAMPMSelection(highlightAMPMSelection);
        timePicker.setHourOfDay(dateTimeCalendar.get(Calendar.HOUR_OF_DAY));
        timePicker.setMinute(dateTimeCalendar.get(Calendar.MINUTE));
        timePicker.onCreateView(dateTimeLayout, null);
        timePicker.setOnClickTimeListener(onTimeClickListener);
        // Construct YearPicker
        listPickerYearView = (ListPickerYearView) dateTimeLayout.findComponentById(ResourceTable.Id_yearPicker);
        listPickerYearView.setMinYear(minimumDateTime.get(Calendar.YEAR));
        listPickerYearView.setMaxYear(maximumDateTime.get(Calendar.YEAR));
        listPickerYearView.assignCurrentYear(dateTimeCalendar.get(Calendar.YEAR));
        listPickerYearView.setDatePickerListener(new OnYearSelectedListener() {
            @Override
            public void onYearSelected(Component view, int yearPicker) {
                dateTimeCalendar.set(Calendar.YEAR, yearPicker);
                yearHeaderValues.setText(yearSimpleDate.format(dateTimeCalendar.getTime()));
                original_year = yearPicker - 1;
                setMonth();
            }
        });
        //BuildDatePicker
        CalendarPicker();

        // Assign buttons
        Button btPositive = (Button) dateTimeLayout.findComponentById(ResourceTable.Id_btPositive);
        Button btNegative = (Button) dateTimeLayout.findComponentById(ResourceTable.Id_btNegative);
        Button btNeutral = (Button) dateTimeLayout.findComponentById(ResourceTable.Id_btNeutral);
        setContentCustomComponent(dateTimeLayout);
        if (isOrientation) {
            setSize(1020, 2280);
        } else {
            setSize(1680, 1020);
            setAlignment(LayoutAlignment.CENTER);
        }

        btPositive.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                if (mListener != null) {
                    mListener.onPositiveButtonClick(dateTimeCalendar.getTime());
                }
                destroy();
            }
        });
        btNegative.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                // Close dialog
                if (mListener != null) {
                    mListener.onNegativeButtonClick(dateTimeCalendar.getTime());
                }
                destroy();
            }
        });
        btNeutral.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                if (mListener != null) {
                    if (mListener instanceof OnButtonWithNeutralClickListener)
                        ((OnButtonWithNeutralClickListener) mListener).onNeutralButtonClick(dateTimeCalendar.getTime());
                }
                destroy();
            }
        });

        if (startAtPosition != UNDEFINED_POSITION){
            viewSwitcher.setCurrentIndex(startAtPosition);
            if (viewSwitcher.getCurrentIndex() == 0) {
                ((RadialPickerLayout) ((DirectionalLayout) viewSwitcher.getCurrentComponent()).getComponentAt(0)).refresh();
            }
        }

    }

    private void CalendarPicker() {
        calendar.set(original_year, original_month, original_day);
        text_month = (Text) dateTimeLayout.findComponentById(ResourceTable.Id_month);
        left_arrow = (Image) dateTimeLayout.findComponentById(ResourceTable.Id_left_arrow);
        left_arrow.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                pageSlider.setCurrentPage(pageSlider.getCurrentPage() - 1);
            }
        });
        right_arrow = (Image) dateTimeLayout.findComponentById(ResourceTable.Id_right_arrow);
        right_arrow.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                pageSlider.setCurrentPage(pageSlider.getCurrentPage() + 1);
            }
        });
        pageSlider = (PageSlider) dateTimeLayout.findComponentById(ResourceTable.Id_pageslider);
        pageProvider = new PageProvider(mContext, calendar);
        pageSlider.setProvider(pageProvider);
        pageSlider.addPageChangedListener(new PageSlider.PageChangedListener() {
            @Override
            public void onPageSliding(int i, float v, int i1) {

            }

            @Override
            public void onPageSlideStateChanged(int i) {
            }

            @Override
            public void onPageChosen(int i) {
                setMonth();
            }
        });

        Calendar calendar = Calendar.getInstance();
        int current_year = calendar.get(Calendar.YEAR);
        int current_month = calendar.get(Calendar.MONTH);
        int diff_year = current_year - original_year;
        int diff_month = current_month - original_month;
        int offset = diff_year * 12 + diff_month;
        pageSlider.setCurrentPage(12);
        setMonth();
    }

    /**
     * 设置月份
     */
    public void setMonth() {
        String s = "";
        String mon = "";
        String mth[];

        int year = original_year;
        int month = original_month + pageSlider.getCurrentPage();
        System.out.println("-->>setMonth = " + original_month + "--" + pageSlider.getCurrentPage());
        if (month > 11) {
            int times = month / 12;
            year = year + times;
            month = month - 12 * times;

        }
        mth = Utils.EN_MOUTH;
        switch (month) {
            case 0:
                s = mth[0] + " " + year;
                mon = mouthArr[0];
                break;
            case 1:
                s = mth[1] + " " + year;
                mon = mouthArr[1];
                break;
            case 2:
                s = mth[2] + " " + year;
                mon = mouthArr[2];
                break;
            case 3:
                s = mth[3] + " " + year;
                mon = mouthArr[3];
                break;
            case 4:
                s = mth[4] + " " + year;
                mon = mouthArr[4];
                break;
            case 5:
                s = mth[5] + " " + year;
                mon = mouthArr[5];
                break;
            case 6:
                s = mth[6] + " " + year;
                mon = mouthArr[6];
                break;
            case 7:
                s = mth[7] + " " + year;
                mon = mouthArr[7];
                break;
            case 8:
                s = mth[8] + " " + year;
                mon = mouthArr[8];
                break;
            case 9:
                s = mth[9] + " " + year;
                mon = mouthArr[9];
                break;
            case 10:
                s = mth[10] + " " + year;
                mon = mouthArr[10];
                break;
            case 11:
                s = mth[11] + " " + year;
                mon = mouthArr[11];
                break;
            default:
                break;
        }
//        text_month.setText(s);
        setTextMonthAnimator(s);
        MessageEvent.month = mon;
        System.out.println("-->>setMonth.MessageEvent.month= "+MessageEvent.month);
        MessageEvent.year = String.valueOf(year);
    }

    private void setTextMonthAnimator(String s){
        if (!text_month.getText().isEmpty() &&!text_month.getText().equals(s)){

            if (animatorGroup != null && animatorGroup.isRunning()){
                text_month.setText(s);
                text_month.setAlpha(1.0f);
                return;
            }
            // 创建动画组对象
            animatorGroup = new AnimatorGroup();
            // 动画1
            AnimatorProperty action1 = new AnimatorProperty();
            action1.setTarget(text_month);
            action1.moveFromY(0).moveByY(-200).setDuration(100);
            action1.setStateChangedListener(new Animator.StateChangedListener() {
                @Override
                public void onStart(Animator animator) {

                }

                @Override
                public void onStop(Animator animator) {

                }

                @Override
                public void onCancel(Animator animator) {

                }

                @Override
                public void onEnd(Animator animator) {
                    text_month.setText(s);
                    text_month.setAlpha(0);
                }

                @Override
                public void onPause(Animator animator) {

                }

                @Override
                public void onResume(Animator animator) {

                }
            });
            // 动画2
            AnimatorProperty action2 = new AnimatorProperty();
            action2.setTarget(text_month);
            action2.moveFromY(0).moveByY(400).setDuration(50);
            // 动画3
            AnimatorProperty action3 = new AnimatorProperty();
            action3.setTarget(text_month);
            action3.moveFromY(0).moveByY(-200).alpha(1.0f).setDuration(100);
            // 先动画1后动画2
            animatorGroup.runSerially(action1, action2, action3);
            animatorGroup.start();
        } else {
            text_month.setText(s);
        }
    }

    /**
     * onMessageEvent
     *
     * @param messageEvent messageEvent
     */
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessageEvent(MessageEvent messageEvent) {

        System.out.println("-->>onMessageEvent = "+MessageEvent.month);
        if (Integer.valueOf(messageEvent.getDay()) < 10) {
            monthAndDayHeaderValues.setText(MessageEvent.month + " 0" + messageEvent.getDay());
        } else {
            monthAndDayHeaderValues.setText(MessageEvent.month +" "+ messageEvent.getDay());
        }

        yearHeaderValues.setText(MessageEvent.year);

        if (isLaChina) {
            mouthArr = Utils.CH_MOUTH;
        } else {
            mouthArr = Utils.EN_MOUTH;
        }

        switch (MessageEvent.month.trim()) {

            case "一月":
                dateTimeCalendar.set(Calendar.MONTH, 0);
                break;
            case "二月":
                dateTimeCalendar.set(Calendar.MONTH, 1);
                break;
            case "三月":
                dateTimeCalendar.set(Calendar.MONTH, 2);
                break;
            case "四月":
                dateTimeCalendar.set(Calendar.MONTH, 3);
                break;
            case "五月":
                dateTimeCalendar.set(Calendar.MONTH, 4);
                break;
            case "六月":
                dateTimeCalendar.set(Calendar.MONTH, 5);
                break;
            case "七月":
                dateTimeCalendar.set(Calendar.MONTH, 6);
                break;
            case "八月":
                dateTimeCalendar.set(Calendar.MONTH, 7);
                break;
            case "九月":
                dateTimeCalendar.set(Calendar.MONTH, 8);
                break;
            case "十月":
                dateTimeCalendar.set(Calendar.MONTH, 9);
                break;
            case "十一月":
                dateTimeCalendar.set(Calendar.MONTH, 10);

                break;
            case "十二月":
                dateTimeCalendar.set(Calendar.MONTH, 11);
                break;
            default:
                break;
        }
        dateTimeCalendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(messageEvent.getDay()));
        viewSwitcher.showPrevious();
        ((RadialPickerLayout) ((DirectionalLayout) viewSwitcher.getCurrentComponent()).getComponentAt(0)).refresh();

        if (mTimeDataSave != null) {
            mTimeDataSave.putInt("positionView", 0);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
        startAtPosition = UNDEFINED_POSITION;

        if (mTimeDataSave != null) {
            mTimeDataSave.putInt("year", dateTimeCalendar.get(Calendar.YEAR));
            mTimeDataSave.putInt("month", dateTimeCalendar.get(Calendar.MONTH));
            mTimeDataSave.putString("monthEn", MessageEvent.month);
            mTimeDataSave.putInt("day", dateTimeCalendar.get(Calendar.DAY_OF_MONTH));
            mTimeDataSave.putInt("hour", dateTimeCalendar.get(Calendar.HOUR_OF_DAY));
            mTimeDataSave.putInt("minute", dateTimeCalendar.get(Calendar.MINUTE));
        }
    }

    /**
     * Define "Time" as the first view to show
     */
    public void startAtTimeView() {
        startAtPosition = HeaderViewsPosition.VIEW_HOURS_AND_MINUTES.getPosition();
    }

    /**
     * Define "Calendar" as the first view to show
     */
    public void startAtCalendarView() {
        startAtPosition = HeaderViewsPosition.VIEW_MONTH_AND_DAY.getPosition();
    }

    /**
     * Define "Year" as the first view to show
     */
    public void startAtYearView() {
        startAtPosition = HeaderViewsPosition.VIEW_YEAR.getPosition();
    }

    /**
     * Assign default year at start
     *
     * @param year year
     */
    public void setDefaultYear(int year) {
        this.dateTimeCalendar.set(Calendar.YEAR, year);
    }

    /**
     * setYear
     *
     * @param year year
     * @deprecated Does not change after launch
     * {@link #setDefaultYear(int)}
     */

    @Deprecated
    public void setYear(int year) {
        setDefaultYear(year);
    }

    /**
     * Assign default month at start (ex: Calendar.DECEMBER)
     *
     * @param month month
     */
    public void setDefaultMonth(int month) {
        this.dateTimeCalendar.set(Calendar.MONTH, month);
    }

    /**
     * setMonth
     *
     * @param month month
     * @deprecated Does not change after launch {@link #setDefaultMonth(int)}
     */
    @Deprecated
    public void setMonth(int month) {
        setDefaultMonth(month);
    }

    /**
     * Assign default day at start
     *
     * @param day day
     */
    public void setDefaultDay(int day) {
        this.dateTimeCalendar.set(Calendar.DAY_OF_MONTH, day);
    }

    /**
     * setDay
     *
     * @param day day
     * @deprecated Does not change after launch
     * {@link #setDefaultDay(int)}
     */
    @Deprecated
    public void setDay(int day) {
        setDefaultDay(day);
    }

    /**
     * Assign default hour of day (in 24 hours) at start
     *
     * @param hourOfDay hourOfDay
     */
    public void setDefaultHourOfDay(int hourOfDay) {
        this.dateTimeCalendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
    }

    /**
     * hour
     *
     * @param hour hour
     * @deprecated Does not change after launch and 24 hours format
     * {@link #setDefaultHourOfDay(int)}
     */
    @Deprecated
    public void setHour(int hour) {
        setDefaultHourOfDay(hour);
    }

    /**
     * Assign default minute at start
     *
     * @param minute minute
     */
    public void setDefaultMinute(int minute) {
        this.dateTimeCalendar.set(Calendar.MINUTE, minute);
    }

    /**
     * setMinute
     *
     * @param minute minute
     * @deprecated Does not change after launch
     * {@link #setDefaultMinute(int)}
     */
    @Deprecated
    public void setMinute(int minute) {
        setDefaultMinute(minute);
    }

    /**
     * Get current year
     *
     * @return dateTimeCalendar dateTimeCalendar
     */
    public int getYear() {
        return this.dateTimeCalendar.get(Calendar.YEAR);
    }

    /**
     * Get current month as Calendar.MONTH
     *
     * @return dateTimeCalendar dateTimeCalendar
     * @see Calendar Calendar
     */
    public int getMonth() {
        return this.dateTimeCalendar.get(Calendar.MONTH);
    }

    /**
     * Get current day
     *
     * @return dateTimeCalendar dateTimeCalendar
     */
    public int getDay() {
        return this.dateTimeCalendar.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * Get current hour of day (hour in 24 hours)
     *
     * @return dateTimeCalendar dateTimeCalendar
     */
    public int getHourOfDay() {
        return this.dateTimeCalendar.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * Get current minute
     *
     * @return dateTimeCalendar dateTimeCalendar
     */
    public int getMinute() {
        return this.dateTimeCalendar.get(Calendar.MINUTE);
    }

    /**
     * Assign default DateTime at start
     *
     * @param date date
     */
    public void setDefaultDateTime(Date date) {
        this.dateTimeCalendar.setTime(date);
        if (mTimeDataSave != null) {
            mTimeDataSave.putInt("year", dateTimeCalendar.get(Calendar.YEAR));
            mTimeDataSave.putInt("month", dateTimeCalendar.get(Calendar.MONTH));
            mTimeDataSave.putInt("day", dateTimeCalendar.get(Calendar.DAY_OF_MONTH));
            mTimeDataSave.putInt("hour", dateTimeCalendar.get(Calendar.HOUR_OF_DAY));
            mTimeDataSave.putInt("minute", dateTimeCalendar.get(Calendar.MINUTE));
        }
        original_month = dateTimeCalendar.get(Calendar.MONTH);
        original_year = dateTimeCalendar.get(Calendar.YEAR) - 1;
    }

    /**
     * Assign minimum DateTime who can be selected
     *
     * @param date date
     */
    public void setMinimumDateTime(Date date) {
        this.minimumDateTime.setTime(date);
    }

    /**
     * Assign maximum DateTime who can be selected
     *
     * @param date date
     */
    public void setMaximumDateTime(Date date) {
        this.maximumDateTime.setTime(date);
    }

    /**
     * Get minimum DateTime who can be selected
     *
     * @return minimumDateTime.getTime() Get minimum DateTime who can be selected
     */
    public Date getMinimumDateTime() {
        return minimumDateTime.getTime();
    }

    /**
     * Get maximum DateTime who can be selected
     *
     * @return maximumDateTime.getTime()  Get maximum DateTime who can be selected
     */
    public Date getMaximumDateTime() {
        return maximumDateTime.getTime();
    }

    /**
     * Return default SimpleDateFormat for Month and Day
     *
     * @return Return default SimpleDateFormat for Month and Day
     */
    public SimpleDateFormat getSimpleDateMonthAndDayFormat() {
        return dayAndMonthSimpleDate;
    }

    /**
     * Assign a SimpleDateFormat like "d MMM" to show formatted DateTime
     *
     * @param simpleDateFormat Format to show month and day
     * @throws SimpleDateMonthAndDayFormatException @throws SimpleDateMonthAndDayFormatException
     */
    public void setSimpleDateMonthAndDayFormat(SimpleDateFormat simpleDateFormat) throws SimpleDateMonthAndDayFormatException {
        Pattern patternMonthAndDay = Pattern.compile("(M|w|W|D|d|F|E|u|\\s)*");
        Matcher matcherMonthAndDay = patternMonthAndDay.matcher(simpleDateFormat.toPattern());
        if (!matcherMonthAndDay.matches()) {
            throw new SimpleDateMonthAndDayFormatException(simpleDateFormat.toPattern() + "isn't allowed for " + patternMonthAndDay.pattern());
        }
        this.dayAndMonthSimpleDate = simpleDateFormat;
    }

    /**
     * Define if time must be in 24 hours mode or in 12 hours, must be applied before "show"
     *
     * @param is24HoursMode is24HoursMode
     */
    public void set24HoursMode(boolean is24HoursMode) {
        this.is24HoursMode = is24HoursMode;
    }

    /**
     * Highlight AM or PM selected, by default AM or PM selected is not highlight. Only works if 24 hours mode is activated
     *
     * @param highlightAMPMSelection true to visually highlight selected item
     */
    public void setHighlightAMPMSelection(boolean highlightAMPMSelection) {
        this.highlightAMPMSelection = highlightAMPMSelection;
    }

    /**
     * Set timezone different from default
     *
     * @param timeZone timeZone
     */
    public void setTimeZone(TimeZone timeZone) {
        if (timeZone != null) {
            this.timeZone = timeZone;
        }
    }

    /**
     * Define if the AlertDialog must be styled, must be applied before "show"
     *
     * @param styleId styleId
     */

    public void setAlertStyle(int styleId) {
        this.alertStyleId = styleId;
    }

    /**
     * Class exception if SimpleDateFormat contains something else that "d" or/and "M"
     */
    public class SimpleDateMonthAndDayFormatException extends Exception {
        SimpleDateMonthAndDayFormatException(String message) {
            super(message);
        }
    }

    /**
     * Callback class for assign action on positive and negative button
     */
    public interface OnButtonClickListener {
        /**
         * onPositiveButtonClick
         *
         * @param date date
         */
        void onPositiveButtonClick(Date date);

        /**
         * onNegativeButtonClick
         *
         * @param date date
         */
        void onNegativeButtonClick(Date date);
    }

    /**
     * Callback class for assign action on positive, negative and neutral button
     */
    public interface OnButtonWithNeutralClickListener extends OnButtonClickListener {
        /**
         * onNeutralButtonClick
         *
         * @param date date
         */
        void onNeutralButtonClick(Date date);
    }

    /**
     * Enumeration of header views
     */
    public enum HeaderViewsPosition {
        VIEW_HOURS_AND_MINUTES(0), VIEW_MONTH_AND_DAY(1), VIEW_YEAR(2);

        private int positionSwitch;

        /**
         * position
         *
         * @param position position
         */
        HeaderViewsPosition(int position) {
            this.positionSwitch = position;
        }

        public int getPosition() {
            return positionSwitch;
        }
    }

    /**
     * Listener for click on Header element
     */
    public class OnClickHeaderElementListener implements Component.ClickedListener {
        private int positionView;

        OnClickHeaderElementListener(int positionView) {
            this.positionView = positionView;
        }

        @Override
        public void onClick(Component view) {
            Utils.animLabelElement(view);
            if (viewSwitcher.getCurrentIndex() != positionView) {
                viewSwitcher.setCurrentIndex(positionView);
                if (viewSwitcher.getCurrentIndex() == 0) {
                    ((RadialPickerLayout) ((DirectionalLayout) viewSwitcher.getCurrentComponent()).getComponentAt(0)).refresh();
                }
            }

            startAtPosition = positionView;
            if (mTimeDataSave != null) {
                mTimeDataSave.putInt("positionView", startAtPosition);
            }
        }
    }
}
